package com.lg.dborder2;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

//参考 https://juejin.im/book/5b4bc28bf265da0f60130116/section/5b4bc28b5188251b1f224ee5
@Slf4j
public class NIOServer {
    Selector serverSelector;

    {
        try {
            serverSelector = Selector.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    Selector clientSelector = Selector.open();

    public NIOServer() throws IOException {
        log.info("lg-NIOServer init");
        new Thread(() -> {
            log.info("lg-NIOServer thread");
            try {
                log.info("lg-NIOServer try");
                // 对应IO编程中服务端启动
                ServerSocketChannel listenerChannel = ServerSocketChannel.open();
                listenerChannel.socket().bind(new InetSocketAddress(8888));
                listenerChannel.configureBlocking(false);
                listenerChannel.register(serverSelector, SelectionKey.OP_ACCEPT);

                while (true) {
                    //log.info("lg-NIOServer while true");
                    // 监测是否有新的连接，这里的1指的是阻塞的时间为 1ms
                    if (serverSelector.select(1) > 0) {
                        log.info("lg-NIOServer 1 > 0");
                        Set<SelectionKey> set = serverSelector.selectedKeys();
                        Iterator<SelectionKey> keyIterator = set.iterator();

                        while (keyIterator.hasNext()) {
                            log.info("lg-NIOServer hasNext");
                            SelectionKey key = keyIterator.next();

                            if (key.isAcceptable()) {
                                log.info("lg-NIOServer key");
                                try {
                                    log.info("lg-NIOServer key try");
                                    // (1) 每来一个新连接，不需要创建一个线程，而是直接注册到clientSelector
                                    SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();
                                    clientChannel.configureBlocking(false);
                                    clientChannel.register(clientSelector, SelectionKey.OP_READ);
                                } finally {
                                    keyIterator.remove();
                                }
                            }

                        }
                    }
                }
            } catch (IOException ignored) {
                log.info("eee");
            }

        }).start();

        new Thread(() -> {
            try {
                while (true) {
                    // (2) 批量轮询是否有哪些连接有数据可读，这里的1指的是阻塞的时间为 1ms
                    if (clientSelector.select(1) > 0) {
                        log.info("lg-client 1 >0 ");
                        Set<SelectionKey> set = clientSelector.selectedKeys();
                        Iterator<SelectionKey> keyIterator = set.iterator();

                        while (keyIterator.hasNext()) {
                            SelectionKey key = keyIterator.next();

                            if (key.isReadable()) {
                                log.info("key isReadable");
                                try {

                                    SocketChannel clientChannel = (SocketChannel) key.channel();
                                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                                    // (3) 面向 Buffer
                                    clientChannel.read(byteBuffer);
                                    byteBuffer.flip();
                                    System.out.println(Charset.defaultCharset().newDecoder().decode(byteBuffer).toString());







//                                    SocketChannel clientChannel = (SocketChannel) key.channel();
//                                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//                                    // (3) 面向 Buffer
//                                    clientChannel.read(byteBuffer);
//                                    byteBuffer.flip();
//                                    String aa = Charset.defaultCharset().newDecoder().decode(byteBuffer).toString();
//                                    log.info("aa {}",aa);
//                                    System.out.println(Charset.defaultCharset().newDecoder().decode(byteBuffer).toString());
//                                    //我懂了哦 因为现在的 byteBuffer 没有东西了
//                                    String bb = Charset.defaultCharset().newDecoder().decode(byteBuffer).toString();
//                                    System.out.println("bb1"+bb);
//                                    System.out.println("bb2"+Charset.defaultCharset().newDecoder().decode(byteBuffer).toString());
//                                    log.info("lg-nio-server1 {}",bb);
//                                    log.info("lg-nio-server2 {}",Charset.defaultCharset().newDecoder().decode(byteBuffer).toString());
                                } finally {
                                    keyIterator.remove();
                                    key.interestOps(SelectionKey.OP_READ);
                                }
                            }

                        }
                    }
                }
            } catch (IOException ignored) {
                log.info("eee2");
            }
        }).start();
    }
}
